home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OLDBARS.PAK / STATBAR.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  21KB  |  789 lines

  1. // statbar.cpp : definition of old backward compatible CStatusBar
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #define _AFX_NO_OLE_SUPPORT
  15. #include <afxpriv.h>
  16. #include "statbar.h"
  17. #include "globals.h"
  18. #ifdef _MAC
  19. #include <macname1.h>
  20. #include <Types.h>
  21. #include <QuickDraw.h>
  22. #include <Fonts.h>
  23. #include <macos\Windows.h>
  24. #include <GestaltEqu.h>
  25. #include <Script.h>
  26. #include <macname2.h>
  27. #endif
  28.  
  29. #ifdef _DEBUG
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33.  
  34. #define new DEBUG_NEW
  35.  
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CStatusBar creation etc
  38.  
  39. struct AFX_STATUSPANE
  40. {
  41.     UINT    nID;        // IDC of indicator: 0 => normal text area
  42.     UINT    nStyle;     // style flags (SBPS_*)
  43.     int     cxText;     // width of string area in pixels
  44.                         //   on both sides there is a 1 pixel gap and
  45.                         //    a one pixel border, making a pane 4 pixels wider
  46.     LPCTSTR  lpszText;  // text in the pane
  47. };
  48.  
  49. inline AFX_STATUSPANE* CStatusBar::_GetPanePtr(int nIndex) const
  50. {
  51.     ASSERT(nIndex >= 0 && nIndex < m_nCount);
  52.     ASSERT(m_pData != NULL);
  53.     return ((AFX_STATUSPANE*)m_pData) + nIndex;
  54. }
  55.  
  56. #ifdef AFX_INIT_SEG
  57. #pragma code_seg(AFX_INIT_SEG)
  58. #endif
  59.  
  60. CStatusBar::CStatusBar()
  61. {
  62.     m_hFont = NULL;
  63.  
  64.     // setup correct margins
  65.     m_cxRightBorder = m_cxDefaultGap;
  66.     m_cxSizeBox = 0;
  67.     m_bHideSizeBox = FALSE;
  68.     if (globalData.bWin4)
  69.     {
  70.         m_cxLeftBorder = 4;
  71.         m_cyTopBorder = 2;
  72.         m_cyBottomBorder = 0;
  73.         m_cxRightBorder = 0;
  74.     }
  75.  
  76.     if (globalData.hStatusFont == NULL)
  77.     {
  78. #ifndef _MAC
  79.         // load status bar font
  80.         CClientDC dc(NULL);
  81.         LOGFONT logfont;
  82.         memset(&logfont, 0, sizeof(logfont));
  83.         logfont.lfWeight = FW_NORMAL;
  84.         logfont.lfHeight = -MulDiv(globalData.bWin4 ? 8 : 10, 
  85.             globalData.cyPixelsPerInch, 72);
  86.         lstrcpy(logfont.lfFaceName, _T("MS Sans Serif"));
  87.         BOOL bCustom = AfxCustomLogFont(AFX_IDS_STATUS_FONT, &logfont);
  88.         if (bCustom || !GetSystemMetrics(SM_DBCSENABLED))
  89.         {
  90.             // only set pitch & family if not a custom font
  91.             if (!bCustom)
  92.                 logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  93.             // 10 point height Sans Serif font (8 point for Win4)
  94.             globalData.hStatusFont = ::CreateFontIndirect(&logfont);
  95.         }
  96. #else
  97.         LONG nFondAndSize;
  98.         nFondAndSize = GetScriptVariable(smSystemScript, smScriptHelpFondSize);
  99.  
  100.         LOGFONT logfont;
  101.         memset(&logfont, 0, sizeof(logfont));
  102.         logfont.lfWeight = FW_NORMAL;
  103.         logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  104.         logfont.lfHeight = -MulDiv(LOWORD(nFondAndSize), globalData.cyPixelsPerInch, 72);
  105.         GetFontName(HIWORD(nFondAndSize), (StringPtr) logfont.lfFaceName);
  106.         p2cstr((StringPtr) logfont.lfFaceName);
  107.         globalData.hStatusFont = ::CreateFontIndirect(&logfont);
  108. #endif
  109.         if (globalData.hStatusFont == NULL)
  110.         {
  111.             if (!GetSystemMetrics(SM_DBCSENABLED))
  112.                 TRACE0("Warning: Using system font for status font.\n");
  113.             globalData.hStatusFont = (HFONT)::GetStockObject(SYSTEM_FONT);
  114.         }
  115.     }
  116. }
  117.  
  118. void CStatusBar::OnWinIniChange(LPCTSTR /*lpszSection*/)
  119. {
  120.     if (globalData.bWin4)
  121.     {
  122.         // get the drawing area for the status bar 
  123.         CRect rect;
  124.         GetClientRect(rect);
  125.         CalcInsideRect(rect, TRUE);
  126.  
  127.         // the size box is based off the size of a scrollbar
  128.         m_cxSizeBox = min(GetSystemMetrics(SM_CXVSCROLL)+1, rect.Height());
  129.     }
  130. }
  131.  
  132. CStatusBar::~CStatusBar()
  133. {
  134.     // free strings before freeing array of elements
  135.     for (int i = 0; i < m_nCount; i++)
  136.         VERIFY(SetPaneText(i, NULL, FALSE));    // no update
  137. }
  138.  
  139. BOOL CStatusBar::PreCreateWindow(CREATESTRUCT& cs)
  140. {
  141.     // in Win4, status bars do not have a border at all, since it is
  142.     //  provided by the client area.
  143.     if (globalData.bWin4 &&
  144.         (m_dwStyle & (CBRS_ALIGN_ANY|CBRS_BORDER_ANY)) == CBRS_BOTTOM)
  145.     {
  146.         m_dwStyle &= ~(CBRS_BORDER_ANY|CBRS_BORDER_3D);
  147.     }
  148.  
  149.     return CControlBar::PreCreateWindow(cs);
  150. }
  151.  
  152. BOOL CStatusBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
  153. {
  154.     ASSERT_VALID(pParentWnd);   // must have a parent
  155.  
  156.     // save the style
  157.     m_dwStyle = (UINT)dwStyle;
  158.  
  159.     // create the HWND
  160.     CRect rect;
  161.     rect.SetRectEmpty();
  162.     LPCTSTR lpszClass = AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW),
  163.         (HBRUSH)(COLOR_BTNFACE+1), NULL);
  164.     if (!CWnd::Create(lpszClass, NULL, dwStyle, rect, pParentWnd, nID))
  165.         return FALSE;
  166.  
  167.     // Note: Parent must resize itself for control bar to be resized
  168.  
  169.     // set initial font and calculate bar height
  170.     SendMessage(WM_SETFONT, (WPARAM)globalData.hStatusFont);
  171.     return TRUE;
  172. }
  173.  
  174. BOOL CStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
  175. {
  176.     ASSERT_VALID(this);
  177.     ASSERT(nIDCount >= 1);  // must be at least one of them
  178.     ASSERT(lpIDArray == NULL ||
  179.         AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));
  180.  
  181.     // free strings before freeing array of elements
  182.     for (int i = 0; i < m_nCount; i++)
  183.         VERIFY(SetPaneText(i, NULL, FALSE));    // no update
  184.  
  185.     // first allocate array for panes and copy initial data
  186.     if (!AllocElements(nIDCount, sizeof(AFX_STATUSPANE)))
  187.         return FALSE;
  188.     ASSERT(nIDCount == m_nCount);
  189.  
  190.     BOOL bOK = TRUE;
  191.     if (lpIDArray != NULL)
  192.     {
  193.         ASSERT(m_hFont != NULL);        // must have a font !
  194.         CString strText;
  195.         CClientDC dcScreen(NULL);
  196.         HGDIOBJ hOldFont = dcScreen.SelectObject(m_hFont);
  197.         for (int i = 0; i < nIDCount; i++)
  198.         {
  199.             AFX_STATUSPANE* pSBP = _GetPanePtr(i);
  200.             pSBP->nID = *lpIDArray++;
  201.             if (pSBP->nID != 0)
  202.             {
  203.                 if (!strText.LoadString(pSBP->nID))
  204.                 {
  205.                     TRACE1("Warning: failed to load indicator string 0x%04X.\n",
  206.                         pSBP->nID);
  207.                     bOK = FALSE;
  208.                     break;
  209.                 }
  210.                 pSBP->cxText = dcScreen.GetTextExtent(strText,
  211.                         strText.GetLength()).cx;
  212.                 ASSERT(pSBP->cxText >= 0);
  213.                 if (!SetPaneText(i, strText, FALSE))
  214.                 {
  215.                     bOK = FALSE;
  216.                     break;
  217.                 }
  218.             }
  219.             else
  220.             {
  221.                 // no indicator (must access via index)
  222.                 // default to 1/4 the screen width (first pane is stretchy)
  223.                 pSBP->cxText = ::GetSystemMetrics(SM_CXSCREEN) / 4;
  224.                 if (i == 0)
  225.                     pSBP->nStyle |= (SBPS_STRETCH | SBPS_NOBORDERS);
  226.             }
  227.         }
  228.         dcScreen.SelectObject(hOldFont);
  229.     }
  230.     return bOK;
  231. }
  232.  
  233. #ifdef AFX_CORE3_SEG
  234. #pragma code_seg(AFX_CORE3_SEG)
  235. #endif
  236.  
  237. /////////////////////////////////////////////////////////////////////////////
  238. // CStatusBar attribute access
  239.  
  240. int CStatusBar::CommandToIndex(UINT nIDFind) const
  241. {
  242.     ASSERT_VALID(this);
  243.  
  244.     if (m_nCount <= 0)
  245.         return -1;
  246.  
  247.     AFX_STATUSPANE* pSBP = _GetPanePtr(0);
  248.     for (int i = 0; i < m_nCount; i++, pSBP++)
  249.         if (pSBP->nID == nIDFind)
  250.             return i;
  251.  
  252.     return -1;
  253. }
  254.  
  255. UINT CStatusBar::GetItemID(int nIndex) const
  256. {
  257.     ASSERT_VALID(this);
  258.     return _GetPanePtr(nIndex)->nID;
  259. }
  260.  
  261. void CStatusBar::GetItemRect(int nIndex, LPRECT lpRect) const
  262. {
  263.     ASSERT_VALID(this);
  264.     ASSERT(AfxIsValidAddress(lpRect, sizeof(RECT)));
  265.  
  266.     // return rectangle containing inset size
  267.     ASSERT(nIndex >= 0 && nIndex < m_nCount);
  268.  
  269.     CRect rect;
  270.     GetClientRect(rect);
  271.     CalcInsideRect(rect, TRUE);
  272.  
  273.     // protect space for size box
  274.     int cxSizeBox = m_bHideSizeBox ? 0 : m_cxSizeBox;
  275.     int xMax = (rect.right -= cxSizeBox);
  276.     if (cxSizeBox == 0)
  277.         xMax += m_cxRightBorder + 1;
  278.  
  279.     // walk through to calculate extra space
  280.     int cxExtra = rect.Width() + m_cxDefaultGap;
  281.     AFX_STATUSPANE* pSBP = (AFX_STATUSPANE*)m_pData;
  282.     for (int i = 0; i < m_nCount; i++, pSBP++)
  283.         cxExtra -= (pSBP->cxText + CX_BORDER * 4 + m_cxDefaultGap);
  284.     // if cxExtra <= 0 then we will not stretch but just clip
  285.  
  286.     for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
  287.     {
  288.         ASSERT(pSBP->cxText >= 0);
  289.         int cxText = pSBP->cxText;
  290.         if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
  291.         {
  292.             cxText += cxExtra;
  293.             cxExtra = 0;
  294.         }
  295.         rect.right = rect.left + cxText + CX_BORDER * 4;
  296.         rect.right = min(rect.right, xMax);
  297.         if (i == nIndex)
  298.             break;  // stop with correct rectangle (includes border)
  299.         rect.left = rect.right + m_cxDefaultGap;
  300.         rect.left = min(rect.left, xMax);
  301.     }
  302.     ASSERT(i == nIndex);
  303.     *lpRect = rect;
  304. }
  305.  
  306. UINT CStatusBar::GetPaneStyle(int nIndex) const
  307. {
  308.     return _GetPanePtr(nIndex)->nStyle;
  309. }
  310.  
  311. void CStatusBar::SetPaneStyle(int nIndex, UINT nStyle)
  312. {
  313.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  314.     if (pSBP->nStyle != nStyle)
  315.     {
  316.         // just change the style of 1 pane, and invalidate it
  317.         pSBP->nStyle = nStyle;
  318.         CRect rect;
  319.         GetItemRect(nIndex, &rect);
  320.         InvalidateRect(rect);
  321.     }
  322. }
  323.  
  324. void CStatusBar::GetPaneInfo(int nIndex, UINT& nID, UINT& nStyle,
  325.     int& cxWidth) const
  326. {
  327.     ASSERT_VALID(this);
  328.  
  329.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  330.     nID = pSBP->nID;
  331.     nStyle = pSBP->nStyle;
  332.     cxWidth = pSBP->cxText;
  333. }
  334.  
  335. void CStatusBar::SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth)
  336. {
  337.     ASSERT_VALID(this);
  338.  
  339.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  340.     pSBP->nID = nID;
  341.     SetPaneStyle(nIndex, nStyle);  // single pane invalidate
  342.     if (cxWidth != pSBP->cxText)
  343.     {
  344.         // change width of one pane -> invalidate the entire status bar
  345.         pSBP->cxText = cxWidth;
  346.         Invalidate();
  347.     }
  348. }
  349.  
  350. void CStatusBar::GetPaneText(int nIndex, CString& s) const
  351. {
  352.     ASSERT_VALID(this);
  353.  
  354.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  355.     s = pSBP->lpszText;
  356. }
  357.  
  358. BOOL CStatusBar::SetPaneText(int nIndex, LPCTSTR lpszNewText, BOOL bUpdate)
  359. {
  360.     ASSERT_VALID(this);
  361.  
  362.     AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  363.     if (pSBP->lpszText != NULL)
  364.     {
  365.         if (lpszNewText != NULL && lstrcmp(pSBP->lpszText, lpszNewText) == 0)
  366.             return TRUE;        // nothing to change
  367.         free((LPVOID)pSBP->lpszText);
  368.     }
  369.  
  370.     BOOL bOK = TRUE;
  371.     if (lpszNewText == NULL || *lpszNewText == '\0')
  372.     {
  373.         pSBP->lpszText = NULL;
  374.     }
  375.     else
  376.     {
  377.         pSBP->lpszText = _tcsdup(lpszNewText);
  378.         if (pSBP->lpszText == NULL)
  379.             bOK = FALSE; // old text is lost and replaced by NULL
  380.     }
  381.  
  382.     if (bUpdate)
  383.     {
  384.         // invalidate the text of the pane - not including the border
  385.         CRect rect;
  386.         GetItemRect(nIndex, &rect);
  387.         if (!(pSBP->nStyle & SBPS_NOBORDERS))
  388.             rect.InflateRect(-CX_BORDER, -CY_BORDER);
  389.         else
  390.             rect.top -= CY_BORDER;  // base line adjustment
  391.         InvalidateRect(rect);
  392.     }
  393.     return bOK;
  394. }
  395.  
  396. /////////////////////////////////////////////////////////////////////////////
  397. // CStatusBar implementation
  398.  
  399. CSize CStatusBar::CalcFixedLayout(BOOL, BOOL bHorz)
  400. {
  401.     ASSERT_VALID(this);
  402.  
  403.     // recalculate based on font height + borders
  404.     TEXTMETRIC tm;
  405.     {
  406.         CClientDC dcScreen(NULL);
  407.         HGDIOBJ hOldFont = dcScreen.SelectObject(m_hFont);
  408.         VERIFY(dcScreen.GetTextMetrics(&tm));
  409.         dcScreen.SelectObject(hOldFont);
  410.     }
  411.  
  412.     CRect rectSize;
  413.     rectSize.SetRectEmpty();
  414.     CalcInsideRect(rectSize, bHorz);    // will be negative size
  415.  
  416.     // sizeof text + 1 or 2 extra on top, 2 on bottom + borders
  417.     return CSize(32767, tm.tmHeight - tm.tmInternalLeading +
  418.         CY_BORDER * (globalData.bWin4 ? 4 : 3) - rectSize.Height());
  419. }
  420.  
  421. void CStatusBar::DoPaint(CDC* pDC)
  422. {
  423.     ASSERT_VALID(this);
  424.     ASSERT_VALID(pDC);
  425.  
  426.     CControlBar::DoPaint(pDC);      // draw border
  427.  
  428.     CRect rect;
  429.     GetClientRect(rect);
  430.     CalcInsideRect(rect, TRUE);
  431.  
  432.     ASSERT(m_hFont != NULL);        // must have a font!
  433.     HGDIOBJ hOldFont = pDC->SelectObject(m_hFont);
  434.  
  435.     // protect space for size box
  436.     int cxSizeBox = m_bHideSizeBox ? 0 : m_cxSizeBox;
  437.     int xMax = (rect.right -= cxSizeBox);
  438.     if (cxSizeBox == 0)
  439.         xMax += m_cxRightBorder + 1;
  440.  
  441.     // walk through to calculate extra space
  442.     int cxExtra = rect.Width() + m_cxDefaultGap;
  443.     AFX_STATUSPANE* pSBP = (AFX_STATUSPANE*)m_pData;
  444.     for (int i = 0; i < m_nCount; i++, pSBP++)
  445.         cxExtra -= (pSBP->cxText + CX_BORDER * 4 + m_cxDefaultGap);
  446.     // if cxExtra <= 0 then we will not stretch but just clip
  447.  
  448.     for (i = 0, pSBP = (AFX_STATUSPANE*)m_pData; i < m_nCount; i++, pSBP++)
  449.     {
  450.         ASSERT(pSBP->cxText >= 0);
  451.         int cxText = pSBP->cxText;
  452.         if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
  453.         {
  454.             cxText += cxExtra;
  455.             cxExtra = 0;
  456.         }
  457.         rect.right = rect.left + cxText + CX_BORDER * 4;
  458.         rect.right = min(rect.right, xMax);
  459.         if (!globalData.bWin32s || pDC->RectVisible(&rect))
  460.             DrawStatusText(pDC, rect, pSBP->lpszText, pSBP->nStyle);
  461.         rect.left = rect.right + m_cxDefaultGap;
  462.         if (rect.left >= xMax)
  463.             break;
  464.     }
  465.     pDC->SelectObject(hOldFont);
  466.  
  467.     // draw the size box in the bottom right corner
  468.     if (cxSizeBox != 0)
  469.     {
  470.         int cxMax = min(cxSizeBox, rect.Height()+m_cyTopBorder);
  471.         rect.left = xMax + (cxSizeBox - cxMax) + CX_BORDER;
  472.         rect.bottom -= CX_BORDER;
  473.         HPEN hPenOld = (HPEN)pDC->SelectObject(globalData.hpenBtnHilite);
  474.         for (int i = 0; i < cxMax; i += 4)
  475.         {
  476.             pDC->MoveTo(rect.left+i, rect.bottom);
  477.             pDC->LineTo(rect.left+cxMax, rect.bottom-cxMax+i);
  478.         }
  479.         pDC->SelectObject(globalData.hpenBtnShadow);
  480.         for (i = 1; i < cxMax; i += 4)
  481.         {
  482.             pDC->MoveTo(rect.left+i, rect.bottom);
  483.             pDC->LineTo(rect.left+cxMax, rect.bottom-cxMax+i);
  484.         }
  485.         for (i = 2; i < cxMax; i += 4)
  486.         {
  487.             pDC->MoveTo(rect.left+i, rect.bottom);
  488.             pDC->LineTo(rect.left+cxMax, rect.bottom-cxMax+i);
  489.         }
  490.         pDC->SelectObject(hPenOld);
  491.     }
  492. }
  493.  
  494. void CStatusBar::DrawStatusText(CDC* pDC, const CRect& rect,
  495.     LPCTSTR lpszText, UINT nStyle)
  496. {
  497.     ASSERT_VALID(pDC);
  498.  
  499.     if (!(nStyle & SBPS_NOBORDERS))
  500.     {
  501.         // draw the borders
  502.         COLORREF clrHilite;
  503.         COLORREF clrShadow;
  504.  
  505.         if (nStyle & SBPS_POPOUT)
  506.         {
  507.             // reverse colors
  508.             clrHilite = globalData.clrBtnShadow;
  509.             clrShadow = globalData.clrBtnHilite;
  510.         }
  511.         else
  512.         {
  513.             // normal colors
  514.             clrHilite = globalData.clrBtnHilite;
  515.             clrShadow = globalData.clrBtnShadow;
  516.         }
  517.         pDC->Draw3dRect(rect, clrShadow, clrHilite);
  518.     }
  519.  
  520.     // just support left justified text
  521.     if (lpszText != NULL && !(nStyle & SBPS_DISABLED))
  522.     {
  523.         CRect rectText(rect);
  524.         if (!(nStyle & SBPS_NOBORDERS)) // only adjust if there are borders
  525.             rectText.InflateRect(-2*CX_BORDER, -CY_BORDER);
  526.         else
  527.             rectText.OffsetRect(0, -CY_BORDER); // baselines line up
  528.  
  529.         // background is already grey
  530.         int nOldMode = pDC->SetBkMode(TRANSPARENT);
  531.         COLORREF crTextColor = pDC->SetTextColor(globalData.clrBtnText);
  532.         COLORREF crBkColor = pDC->SetBkColor(globalData.clrBtnFace);
  533.  
  534.         // align on bottom (since descent is more important than ascent)
  535.         pDC->SetTextAlign(TA_LEFT | TA_BOTTOM);
  536.         pDC->ExtTextOut(rectText.left, rectText.bottom,
  537.             ETO_CLIPPED, &rectText, lpszText, lstrlen(lpszText), NULL);
  538.     }
  539. }
  540.  
  541. /////////////////////////////////////////////////////////////////////////////
  542. // CStatusBar message handlers
  543.  
  544. BEGIN_MESSAGE_MAP(CStatusBar, CControlBar)
  545.     //{{AFX_MSG_MAP(CStatusBar)
  546.     ON_WM_NCHITTEST()
  547.     ON_WM_SYSCOMMAND()
  548.     ON_WM_SIZE()
  549.     ON_MESSAGE(WM_SETFONT, OnSetFont)
  550.     ON_MESSAGE(WM_GETFONT, OnGetFont)
  551.     ON_MESSAGE(WM_SETTEXT, OnSetText)
  552.     ON_MESSAGE(WM_GETTEXT, OnGetText)
  553.     ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)
  554.     ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
  555.     ON_WM_WININICHANGE()
  556.     //}}AFX_MSG_MAP
  557. END_MESSAGE_MAP()
  558.  
  559. UINT CStatusBar::OnNcHitTest(CPoint point)
  560. {
  561.     // hit test the size box - convert to HTCAPTION if so
  562.     if (!m_bHideSizeBox && m_cxSizeBox != 0)
  563.     {
  564.         CRect rect;
  565.         GetClientRect(rect);
  566.         CalcInsideRect(rect, TRUE);
  567.         int cxMax = min(m_cxSizeBox-1, rect.Height());
  568.         rect.left = rect.right - cxMax;
  569.         ClientToScreen(&rect);
  570.         if (rect.PtInRect(point))
  571.             return HTBOTTOMRIGHT;
  572.     }
  573.     return CControlBar::OnNcHitTest(point);
  574. }
  575.  
  576. void CStatusBar::OnSysCommand(UINT nID, LPARAM lParam)
  577. {
  578.     if (!m_bHideSizeBox && m_cxSizeBox != 0 && (nID & 0xFFF0) == SC_SIZE)
  579.     {
  580.         CFrameWnd* pFrameWnd = GetParentFrame();
  581.         if (pFrameWnd != NULL)
  582.         {
  583.             pFrameWnd->SendMessage(WM_SYSCOMMAND, (WPARAM)nID, lParam);
  584.             return;
  585.         }
  586.     }
  587.     CControlBar::OnSysCommand(nID, lParam);
  588. }
  589.  
  590. void CStatusBar::OnSize(UINT nType, int cx, int cy)
  591. {
  592.     CControlBar::OnSize(nType, cx, cy);
  593.  
  594.     // adjust m_cxSizeBox if necessary
  595.     OnWinIniChange(NULL);    
  596.  
  597.     // force repaint on resize (recalculate stretchy)
  598.     Invalidate();
  599. }
  600.  
  601. LRESULT CStatusBar::OnSetFont(WPARAM wParam, LPARAM)
  602. {
  603.     m_hFont = (HFONT)wParam;
  604.     ASSERT(m_hFont != NULL);
  605.  
  606.     return 0L;      // does not re-draw or invalidate - resize parent instead
  607. }
  608.  
  609. LRESULT CStatusBar::OnGetFont(WPARAM, LPARAM)
  610. {
  611.     return (LRESULT)(UINT)m_hFont;
  612. }
  613.  
  614. LRESULT CStatusBar::OnSetText(WPARAM, LPARAM lParam)
  615. {
  616.     int nIndex = CommandToIndex(0);
  617.     if (nIndex < 0)
  618.         return -1;
  619.     return SetPaneText(nIndex, (LPCTSTR)lParam) ? 0 : -1;
  620. }
  621.  
  622. LRESULT CStatusBar::OnGetText(WPARAM wParam, LPARAM lParam)
  623. {
  624.     int nMaxLen = (int)wParam;
  625.     if (nMaxLen == 0)
  626.         return 0;       // nothing copied
  627.     LPTSTR lpszDest = (LPTSTR)lParam;
  628.  
  629.     int nLen = 0;
  630.     int nIndex = CommandToIndex(0); // use pane with ID zero
  631.     if (nIndex >= 0)
  632.     {
  633.         AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  634.         nLen = pSBP->lpszText != NULL ? lstrlen(pSBP->lpszText) : 0;
  635.         if (nLen > nMaxLen)
  636.             nLen = nMaxLen - 1; // number of characters to copy (less term.)
  637.         memcpy(lpszDest, pSBP->lpszText, nLen*sizeof(TCHAR));
  638.     }
  639.     lpszDest[nLen] = '\0';
  640.     return nLen+1;      // number of bytes copied
  641. }
  642.  
  643. LRESULT CStatusBar::OnGetTextLength(WPARAM, LPARAM)
  644. {
  645.     int nLen = 0;
  646.     int nIndex = CommandToIndex(0); // use pane with ID zero
  647.     if (nIndex >= 0)
  648.     {
  649.         AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
  650.         if (pSBP->lpszText != NULL)
  651.             nLen = lstrlen(pSBP->lpszText);
  652.     }
  653.     return nLen;
  654. }
  655.  
  656. LRESULT CStatusBar::OnSizeParent(WPARAM wParam, LPARAM lParam)
  657. {
  658.     AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
  659.     if (lpLayout->hDWP != NULL)
  660.     {
  661.         // hide size box if parent is maximized
  662.         CFrameWnd* pFrameWnd = GetParentFrame();
  663.         if (pFrameWnd != NULL)
  664.         {
  665.             // the size box only appears when status bar is on the bottom
  666.             //  of a non-maximized, sizeable frame window.
  667.             CRect rectFrame;
  668.             pFrameWnd->GetClientRect(rectFrame);
  669.             BOOL bHideSizeBox = pFrameWnd->IsZoomed() ||
  670.                 !(pFrameWnd->GetStyle() & WS_THICKFRAME) ||
  671.                 rectFrame.bottom != lpLayout->rect.bottom ||
  672.                 rectFrame.right != lpLayout->rect.right;
  673.  
  674.             // update the size box hidden status, if changed
  675.             if (bHideSizeBox != m_bHideSizeBox)
  676.             {
  677.                 m_bHideSizeBox = bHideSizeBox;
  678.                 Invalidate();
  679.             }
  680.         }
  681.     }
  682.  
  683.     return CControlBar::OnSizeParent(wParam, lParam);
  684. }
  685.  
  686. /////////////////////////////////////////////////////////////////////////////
  687. // CStatusBar idle update through CStatusCmdUI class
  688.  
  689. #define CStatusCmdUI COldStatusCmdUI
  690.  
  691. class CStatusCmdUI : public CCmdUI      // class private to this file!
  692. {
  693. public: // re-implementations only
  694.     virtual void Enable(BOOL bOn);
  695.     virtual void SetCheck(int nCheck);
  696.     virtual void SetText(LPCTSTR lpszText);
  697. };
  698.  
  699. void CStatusCmdUI::Enable(BOOL bOn)
  700. {
  701.     m_bEnableChanged = TRUE;
  702.     CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
  703.     ASSERT(pStatusBar != NULL);
  704.     ASSERT_KINDOF(CStatusBar, pStatusBar);
  705.     ASSERT(m_nIndex < m_nIndexMax);
  706.  
  707.     UINT nNewStyle = pStatusBar->GetPaneStyle(m_nIndex) & ~SBPS_DISABLED;
  708.     if (!bOn)
  709.         nNewStyle |= SBPS_DISABLED;
  710.     pStatusBar->SetPaneStyle(m_nIndex, nNewStyle);
  711. }
  712.  
  713. void CStatusCmdUI::SetCheck(int nCheck) // "checking" will pop out the text
  714. {
  715.     CStatusBar* pStatusBar = (CStatusBar*)m_pOther;
  716.     ASSERT(pStatusBar != NULL);
  717.     ASSERT_KINDOF(CStatusBar, pStatusBar);
  718.     ASSERT(m_nIndex < m_nIndexMax);
  719.  
  720.     UINT nNewStyle = pStatusBar->GetPaneStyle(m_nIndex) & ~SBPS_POPOUT;
  721.     if (nCheck != 0)
  722.         nNewStyle |= SBPS_POPOUT;
  723.     pStatusBar->SetPaneStyle(m_nIndex, nNewStyle);
  724. }
  725.  
  726. void CStatusCmdUI::SetText(LPCTSTR lpszText)
  727. {
  728.     ASSERT(m_pOther != NULL);
  729.     ASSERT_KINDOF(CStatusBar, m_pOther);
  730.     ASSERT(m_nIndex < m_nIndexMax);
  731.  
  732.     ((CStatusBar*)m_pOther)->SetPaneText(m_nIndex, lpszText);
  733. }
  734.  
  735. void CStatusBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
  736. {
  737.     CStatusCmdUI state;
  738.     state.m_pOther = this;
  739.     state.m_nIndexMax = (UINT)m_nCount;
  740.     for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
  741.         state.m_nIndex++)
  742.     {
  743.         state.m_nID = _GetPanePtr(state.m_nIndex)->nID;
  744.         state.DoUpdate(pTarget, bDisableIfNoHndler);
  745.     }
  746.  
  747.     // update the dialog controls added to the status bar
  748.     UpdateDialogControls(pTarget, bDisableIfNoHndler);
  749. }
  750.  
  751. /////////////////////////////////////////////////////////////////////////////
  752. // CStatusBar diagnostics
  753.  
  754. #ifdef _DEBUG
  755. void CStatusBar::AssertValid() const
  756. {
  757.     CControlBar::AssertValid();
  758. }
  759.  
  760. void CStatusBar::Dump(CDumpContext& dc) const
  761. {
  762.     CControlBar::Dump(dc);
  763.  
  764.     dc << "\nm_hFont = " << (UINT)m_hFont;
  765.  
  766.     if (dc.GetDepth() > 0)
  767.     {
  768.         for (int i = 0; i < m_nCount; i++)
  769.         {
  770.             dc << "\nstatus pane[" << i << "] = {";
  771.             dc << "\n\tnID = " << _GetPanePtr(i)->nID;
  772.             dc << "\n\tnStyle = " << _GetPanePtr(i)->nStyle;
  773.             dc << "\n\tcxText = " << _GetPanePtr(i)->cxText;
  774.             dc << "\n\tlpszText = " << _GetPanePtr(i)->lpszText;
  775.             dc << "\n\t}";
  776.         }
  777.     }
  778.  
  779.     dc << "\n";
  780. }
  781. #endif //_DEBUG
  782.  
  783. #undef new
  784. #ifdef AFX_INIT_SEG
  785. #pragma code_seg(AFX_INIT_SEG)
  786. #endif
  787.  
  788. IMPLEMENT_DYNAMIC(CStatusBar, CControlBar)
  789.